package jmind.core.geo;

/**
 * 1,自己利用球面坐标计算两点距离的方法：（可以自己后台运算）
 设地球半径为R，地心为0，球面上两点A、B的球面坐标为A（α1，β1），B（α2，β2），α1、α2∈[-π，π]，β1、β2∈[-π/2，π/2 ]， 

AB =R•arccos[cosβ1cosβ2cos（α1-α2）+sinβ1sinβ2] 
利用勾股定理与正弦定理则可求出AB两点间的直线距离，在利用正弦定理可求出AB两点与地球0点夹角的度数，再利用如下公式：角EOD的度数/360度=E与D之间的球面距离/大圆周长，则可求出AB的球面距离。

注意，R = 6370996.81米。

2,自己利用平面坐标系计算两点距离的方法：
由百度经纬度得到摩卡托坐标后，能轻松计算出X和Y的值。最后用勾股定理求得Z。
alert(Math.sqrt(Math.pow((12057394.71 - 12058626.7),2) + Math.pow((2589680.88 - 2592552.85),2)));

 * @author weibo-xie
 * 2012-7-24
 */
public class Distance {

    public static void main(String[] args) {
        double x1 = 39.992792, y1 = 116.326142;
        double x2 = 39.99676822857143, y2 = 116.33298485714285;

        System.out.println(gps2m(x1, y1, x2, y2));
        double calDistance = getDistance(x1, y1, x2, y2);
        System.out.println(calDistance);

        double distance2 = distance(x1, y1, x2, y2);
        System.out.println(distance2);
        System.out.println(distance2(x1, y1, x2, y2));

    }

    /**
     * 地球平均半径 6371.004千米 地球赤道半径 6378.140千米 地球极地半径 6356.755千米 
     */
    private static double EARTH_RADIUS = 6371.229; //6378.137; // km

    /**
     * 其实就是球面距离算法
    lat是纬度，lung是经度
    a=Lat1 – Lat2 为两点纬度之差  b=Lung1 -Lung2 为两点经度之差；
    6378.137（KM） 为地球半径 - -@
    恩，结果也是km……
     * @param lat_a
     * @param lng_a
     * @param lat_b
     * @param lng_b
     * @return
     */
    public static double gps2m(double lat_a, double lng_a, double lat_b, double lng_b) {
        double radLat1 = (lat_a * Math.PI / 180.0);
        double radLat2 = (lat_b * Math.PI / 180.0);
        double a = radLat1 - radLat2;
        double b = (lng_a - lng_b) * Math.PI / 180.0;
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2)
                * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS * 1000;
        s = Math.round(s * 10000) / 10000;
        return s;
    }

    private static double rad(double d) {
        return d * Math.PI / 180.0;
    }

    /**
     *   Google Map上的根据经纬度求地球表面两点间距离的实现
     * @param lat1  纬度
     * @param lat2  经度
     * @param lon1
     * @param lon2
     * @return
     */
    public static double getDistance(double lat1, double lng1, double lat2, double lng2) {
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double a = radLat1 - radLat2;
        double b = rad(lng1) - rad(lng2);
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2)
                * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS * 1000;
        //   s = Math.round(s * 10000) / 10000;
        return s;
    }

    public static double distance(double lat1, double lat2, double lon1, double lon2) {

        double distance = 0.0;
        double dLat = (lat2 - lat1) * Math.PI / 180;
        double dLon = (lon2 - lon1) * Math.PI / 180;
        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat1 * Math.PI / 180)
                * Math.cos(lat2 * Math.PI / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
        distance = (2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))) * EARTH_RADIUS;
        return distance;
    }

    public static double distance2(double n1, double e1, double n2, double e2) {
        double jl_jd = 102834.74258026089786013677476285;
        double jl_wd = 111712.69150641055729984301412873;
        double b = Math.abs((e1 - e2) * jl_jd);
        double a = Math.abs((n1 - n2) * jl_wd);
        return Math.sqrt((a * a + b * b));

    }

}
